#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <pthread.h>

#define PORT 8888
#define QUIT_STR "quit"


void *data_handle(void *arg);

int main(int argc, const char * argv[]) 
{
    //1.创建监听的套接字
    int lfd = socket(AF_INET, SOCK_STREAM, 0);
    if (lfd == -1)
    {
	perror("socket error\n");
	exit(1);
    }

    //2.lfd和本地的IP和port绑定
    struct sockaddr_in server;
    memset(&server, 0, sizeof(server));
    server.sin_family = AF_INET;  //地址族协议  ipv4
    server.sin_port = htons(PORT); //端口号
    server.sin_addr.s_addr = htonl(INADDR_ANY); //ip地址
    int ret = bind(lfd, (struct sockaddr*)&server, sizeof(server));
    if (ret == -1)
    {
	perror("bind error\n");
	exit(1);
    }


    //3.设置监听
    ret = listen(lfd, 20);
    if (ret == -1)
    {
	perror("listen error\n");
	exit(1);
    }

    //4.等待并接受连接请求
    struct sockaddr_in client;
    pthread_t pid;
    socklen_t len = sizeof(client);
    while(1)
    {
	int cfd = accept(lfd, (struct sockaddr*)&client, &len);
	if (cfd == -1)
	{
	    perror("accept error");
	    exit(1);
	}

	//获取客户端数据
	printf("accept successful\n");
	char ipbuf[64] = {0};
	inet_ntop(AF_INET, &client.sin_addr.s_addr, ipbuf, sizeof(ipbuf)); //获取客户端ip
	printf("client File descriptor:%d IP:%s, port:%d\n", cfd, ipbuf, ntohs(client.sin_port));

	pthread_create(&pid, NULL, data_handle, (void *)&cfd); //创建子线程进行读写操作
	pthread_detach(pid); //子线程分离,防止僵线程产生.
    }

    return 0;
}

//子线程
void *data_handle(void *arg)
{
    int cfd = *(int *)arg;

    //接收数据
    char buf[1024];
    while (1)
    {
	bzero(buf, sizeof(buf));
	int len = read(cfd, buf, sizeof(buf));
	if(len == -1)
	{
	    perror("read error\n");
	    exit(1);
	}
	else if (len == 0)
	{
	    break;
	}
	else
	{
	    printf("client File descriptor:%d, recv buf: %s", cfd, buf);
	    if (!strncasecmp(buf, QUIT_STR, strlen(QUIT_STR))) 
	    {
		printf("client File descriptor %d is exiting\n", cfd);
		break;
	    }
	}
    }

    close(cfd);
    return NULL;

